<?php
/**
 *  Each element in the tree is wrapped by a Yz_Tree_Interface element
 *  A tree element implements both its own methods and the whole tree's ones
 *
 *  Concrete implementations can also add methods such as:
 *  - fetch element by key other than ID
 *
 *  Examples:
 *  1. a department/employee structure: $empTree
 *      - level 0: the CEO, element id=1
 *      - level 1: the top management
 *      - level 2: the dept heads
 *      - level 3: staff
 *    get employee data, id=1234, depth=3:
 *      $empTree[1234].element.name: "John Doe"
 *      $empTree[1234].parent: <TreeElement>(id=123,depth=2)
 *      $empTree[123].children: Array[<TreeElement>(id=123), ...]
 *      $empTree[123].parent: <TreeElement>(id=12,depth=1)
 *    get the complete branch:
 *      $br = $empTree[12].branch: <TreeElement>(id=12,depth=0), children: array[<TreeElement>(id=123), ...]
 *      $br[1234]: <TreeElement>(id=1234,depth=2)
 *      $br[1234].element.name: "John Doe"
 *
 *
 */
interface Yz_Tree_Interface
{

    public function createElement($id, $value);

    /**
     *  apply callback recursively to each element of the tree (i.e. all descendants of the element)
     *  Note: the processing order depends on implementation
     */
#    public function apply($callback);

    /**
     *  get a branch (as Tree) starting from this element as root
     *  @return Yz_Tree_Interface : a copy of all elements
     */
    #public function branch();

    /**
     *  apply callback to each element of the tree
     *  Note: the processing order depends on implementation
     */
    #public function reduce($callback);

    /**
     *  get the root element of the tree
     *  ### the pseudo root doesn't matter, and there can be many elements at depth=1
     */
    ///public function getRootElement();

    /**
     *  get the tree flattened
     *  Note: the processing order depends on implementation
     *  - either depth-based (elements with the smaller depth level go earlier)
     *  - or recursion-based (the children of the first child etc)
     *  the latter is more practical
     */
    public function toArray();

    /**
     *  apply callback recursively to each element of the tree (i.e. all descendants of the element)
     *  Note: the processing order depends on implementation
     *
     *  @param callback function(element) : void/ignored
     *  @return chainable
     */
    public function apply($callback);

}
